package org.lex.utils.logging.handler;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.StreamHandler;
import java.util.prefs.Preferences;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.WindowConstants;
import javax.swing.border.EmptyBorder;

import org.lex.swing.Option;
import org.lex.swing.fontchooser.JFontChooser;
import org.lex.swing.widgets.OutputStreamTextArea;
import org.lex.utils.SystemProperties;


public class WindowHandler extends JFrame {
	private final static boolean ALWAYS_OP_TOP = true;
	private final static String ROOT_PATH = "/org/svchost/component/" + "util/logging/handler/WindowHandler";
	private final static String FONT_PATH = ROOT_PATH + "/font";

	private final static String FONT_FAMILY = "family";
	private final static String FONT_SIZE = "size";
	private final static String FONT_STYLE = "style";
	private final static String FORMATTER = "formatter";

	private JPanel pane = null;
	private JScrollPane scrollPane = null;
	private OutputStreamTextArea textArea = null;
	private JToolBar toolBar = null;
	private JToggleButton onTopToggleButton = null;
	private JButton saveButton = null;
	private JButton fontButton = null;
	private JComboBox formatterComboBox = null;
	// ================================
	private Handler handler = null;

	public WindowHandler() {
		super();
		initialize();
	}

	public Handler getHandler() {
		if (null == handler) {
			Formatter f = LogFormatter.parseFromDisplayName(loadFormatterName()).getFormatter();
			handler = new StreamHandler(textArea.getOutputStream(), f) {
				public synchronized void publish(LogRecord record) {
					super.publish(record);
					super.flush();
				}
			};
		}
		return handler;
	}

	/*
	 * ��Preferences�ж���/��������
	 */
	private Font loadFont() {
		// ���緢���κδ��󣬶��᷵��null
		try {
			Preferences p = Preferences.userRoot().node(FONT_PATH);
			String name = p.get(FONT_FAMILY, "Default");
			int size = p.getInt(FONT_SIZE, 12);
			int style = p.getInt(FONT_STYLE, Font.PLAIN);
			return new Font(name, style, size);
		} catch (Throwable t) {
			return null;
		}
	}

	private void saveFont(Font font) {
		if (null == font)
			return;
		String name = font.getFamily();
		int size = font.getSize();
		int style = font.getStyle();
		try {
			Preferences p = Preferences.userRoot().node(FONT_PATH);
			p.put(FONT_FAMILY, name);
			p.putInt(FONT_SIZE, size);
			p.putInt(FONT_STYLE, style);
			p.flush();
		} catch (Throwable t) {

		}
	}

	private String loadFormatterName() {
		// ���緢���κδ��󣬶��᷵��ȱʡ��Formatter
		String def = LogFormatter.DEFAULT_FORMATTER.getDisplayName();
		try {
			Preferences p = Preferences.userRoot().node(ROOT_PATH);
			return p.get(FORMATTER, def);
		} catch (Throwable t) {
			return def;
		}
	}

	private void saveFormatterName(String name) {
		if (null == name)
			return;
		try {
			Preferences p = Preferences.userRoot().node(ROOT_PATH);
			p.put(FORMATTER, name);
			p.flush();
		} catch (Throwable t) {

		}
	}

	private void initialize() {
		this.setSize(400, 420);
		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		this.setAlwaysOnTop(ALWAYS_OP_TOP);
		this.setContentPane(getPane());
	}

	private JPanel getPane() {
		if (pane == null) {
			pane = new JPanel();
			pane.setLayout(new BorderLayout());
			pane.add(getScrollPane(), BorderLayout.CENTER);
			pane.add(getToolBar(), BorderLayout.NORTH);
		}
		return pane;
	}

	private JScrollPane getScrollPane() {
		if (scrollPane == null) {
			scrollPane = new JScrollPane();
			scrollPane.setViewportView(getTextArea());
		}
		return scrollPane;
	}

	private OutputStreamTextArea getTextArea() {
		if (textArea == null) {
			textArea = new OutputStreamTextArea();
			textArea.setAutoScrollText(true);
			textArea.setTextAntialiasEnabled(true);
			textArea.setBorder(new EmptyBorder(2, 2, 0, 0));
			Font font = this.loadFont();
			if (null != font)
				textArea.setFont(font);
		}
		return textArea;
	}

	private JToolBar getToolBar() {
		if (toolBar == null) {
			toolBar = new JToolBar();
			toolBar.add(getSaveButton());
			toolBar.addSeparator();
			toolBar.add(getFontButton());
			toolBar.addSeparator();
			toolBar.add(new JLabel("Format "));
			toolBar.add(this.getFormatterComboBox());
			toolBar.add(Box.createHorizontalGlue());
			toolBar.add(getOnTopToggleButton());
		}
		return toolBar;
	}

	private JToggleButton getOnTopToggleButton() {
		if (onTopToggleButton == null) {
			onTopToggleButton = new JToggleButton();
			onTopToggleButton.setText("Always On Top");
			onTopToggleButton.setSelected(ALWAYS_OP_TOP);
			onTopToggleButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					setAlwaysOnTop(onTopToggleButton.isSelected());
				}
			});
		}
		return onTopToggleButton;
	}

	private JButton getSaveButton() {
		if (saveButton == null) {
			saveButton = new JButton();
			saveButton.setText("Save");
		}
		return saveButton;
	}

	private JButton getFontButton() {
		if (fontButton == null) {
			fontButton = new JButton();
			fontButton.setText("Font");
			fontButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					JFontChooser jfc = new JFontChooser();
					jfc.setFont(getTextArea().getFont());
					Option opt = jfc.showDialog(WindowHandler.this);
					if (opt.isYesOption()) {
						Font font = jfc.getFont();
						getTextArea().setFont(font);
						saveFont(font);
					}
				}
			});
		}
		return fontButton;
	}

	private JComboBox getFormatterComboBox() {
		if (null == this.formatterComboBox) {
			formatterComboBox = new JComboBox(LogFormatter.getDiaplayNames()) {
				public Dimension getMaximumSize() {
					Dimension d = super.getPreferredSize();
					d.width += 50;
					return d;
				}
			};
			formatterComboBox.setSelectedItem(this.loadFormatterName());
			formatterComboBox.addActionListener(new ActionListener() {
				String newline = SystemProperties.lineSeparator();

				public void actionPerformed(ActionEvent e) {
					Object o = formatterComboBox.getSelectedItem();
					if (null == o)
						return;
					String name = String.valueOf(o);
					Formatter f = LogFormatter.parseFromDisplayName(name).getFormatter();
					getHandler().setFormatter(f);
					getTextArea().append(newline);
					getTextArea().append(WindowHandler.class.getName());
					getTextArea().append("  Formatter Changed to: ");
					getTextArea().append(name);
					getTextArea().append(newline);
					saveFormatterName(name);
				}
			});
		}
		return formatterComboBox;
	}
}
